/*
 * Monte Carlo application controller 
 */
package javaapplication6.CONTROLLER;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import javaapplication6.MODEL.AbstractMonteCarloSimulation;
import javaapplication6.MODEL.MULTI.MonteCarloSimulationMulti;
import javaapplication6.MODEL.SINGLE.MonteCarloSimulation;
import javax.swing.JTextField;

/**
 * Monte carlo simulation Controller class (MVC)
 * @author mathieubakrim
 */
public class MonteCarloSimulationController { 
    
    private final String filePath = "setOfValues.csv"; // file name of the set of values used for presets
    private final String separator = ";";// separator used in the csv file
    
    private long executionTime;
    
    private AbstractMonteCarloSimulation simulation;
    private String threadingMode; // single or multi
    private List<AbstractMonteCarloSimulation> theMonteCarloSimulationsPreset;
    
    
     /**
     * Main method to compute a simulation (single or multi threaded)
     * @param tabJtf contains all the simulation values from the GUI
     * @param f flag determining the option type (call or put)
     * @param a preset argument used
     * @param threadingMode specify single or multi threaded simulation to compute
     * @return the monte Carlo simulation option price
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public double computeSimulation(JTextField[] tabJtf, String f, String a, String threadingMode) throws InterruptedException, ExecutionException {
        double s = Double.parseDouble(tabJtf[0].getText());
        double x = Double.parseDouble(tabJtf[1].getText());
        double t = Double.parseDouble(tabJtf[2].getText());
        double r = Double.parseDouble(tabJtf[3].getText());
        double b = Double.parseDouble(tabJtf[4].getText());
        double v = Double.parseDouble(tabJtf[5].getText());
        int nSteps = Integer.parseInt(tabJtf[6].getText());
        int nSimulations = Integer.parseInt(tabJtf[7].getText());
        String flag = f;
        this.threadingMode = threadingMode; 
        double computedValue = -1;
      
        if(threadingMode.equals("Single")){
             simulation = new MonteCarloSimulation();
             computedValue = simulation.MonteCarloStandardOption(flag, s, x, t, r, b, v, nSteps, nSimulations);   
             System.out.println("Computing single threaded mode");
        }else if(threadingMode.equals("Multi")){
            simulation = new MonteCarloSimulationMulti();
            computedValue = simulation.MonteCarloStandardOption(flag, s, x, t, r, b, v, nSteps, nSimulations); 
            System.out.println("Computing multi threaded mode");
        }
        
        executionTime = simulation.getEnd() - simulation.getStart();
        
        return  computedValue;
    }
       
    /**
     * CSV reader used to read a set of values from file
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public void csvReader() throws FileNotFoundException, IOException{
        BufferedReader reader = new BufferedReader(new FileReader(filePath));
        String csvSimulation = null;
        
        theMonteCarloSimulationsPreset = new ArrayList<AbstractMonteCarloSimulation>();
        // Uncomment if we want to add titles in file
        //reader.readLine(); // avoid to retrieve the title line as a contact
        
        while((csvSimulation = reader.readLine()) != null){
            MonteCarloSimulation simu = new MonteCarloSimulation();
            String[] simulationInfoData = csvSimulation.split(separator);
            simu.setS(Double.parseDouble(simulationInfoData[0]));
            simu.setX(Double.parseDouble(simulationInfoData[1]));
            simu.setT(Double.parseDouble(simulationInfoData[2]));
            simu.setR(Double.parseDouble(simulationInfoData[3]));
            simu.setB(Double.parseDouble(simulationInfoData[4]));
            simu.setV(Double.parseDouble(simulationInfoData[5]));
            simu.setnSteps(Integer.parseInt(simulationInfoData[6]));
            simu.setnSimulations(Integer.parseInt(simulationInfoData[7]));
            
            theMonteCarloSimulationsPreset.add(simu);
        }
    }
    
    /**
     * CSV Writer used to save the modified preset list of simulation parameters
     * @throws IOException 
     */
    public void csvWriter() throws IOException{
        BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, false));
        /*
         * Uncomment if we want to add titles
         * for(int i = 0; i< contactsTable.getTitles().length; i++){
            writer.write(contactsTable.getTitles()[i] + separator);
        }
        */
                
        for(int i = 0; i < theMonteCarloSimulationsPreset.size(); i++){
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getS())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getX())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getT())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getR())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getB())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getV())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getnSteps())+ separator);
            writer.write(String.valueOf(theMonteCarloSimulationsPreset.get(i).getnSimulations())+ separator);
            writer.newLine();
        }
        writer.close();
   }

    /**
     * This method is called before the CSV writer in order to refresh the simulation attributes 
     * stocked in memory
     * @param jtfs the parameters typed by the user on the dialog frame
     * @param pos the position of the preset in the preset array
     */
    public void updateData(JTextField[] jtfs, int pos){       
        simulation = theMonteCarloSimulationsPreset.get(pos);
        simulation.setS(Double.parseDouble(jtfs[0].getText()));
        simulation.setX(Double.parseDouble(jtfs[1].getText()));
        simulation.setT(Double.parseDouble(jtfs[2].getText()));
        simulation.setR(Double.parseDouble(jtfs[3].getText()));
        simulation.setB(Double.parseDouble(jtfs[4].getText()));
        simulation.setV(Double.parseDouble(jtfs[5].getText()));
        simulation.setnSteps(Integer.parseInt(jtfs[6].getText()));
        simulation.setnSimulations(Integer.parseInt(jtfs[7].getText()));
        theMonteCarloSimulationsPreset.set(pos, simulation);
    }
    
    /**
     * Get the preset parameters to send to the GUI combo box
     * @return a list of monte Carlo simulation presets
     */
    public List<AbstractMonteCarloSimulation> getTheMonteCarloSimulationsPreset() {
        return Collections.unmodifiableList(theMonteCarloSimulationsPreset);
    }    
    
    /**
     * Getter used tom measure the computing time
     * @return 
     */
    public long getExecutionTime(){
        return executionTime;
    }
}
